/* eslint-disable jsdoc/no-restricted-syntax */
// moduleWrapper.mjs
console.log("Load ModuleWrapper");

/**
 * @template {object} O
 * @template {string} N
 * @template {() => any} L
 * @param {O} object
 * @param {N} name
 * @param {L} lambda
 * @returns {O & {[name in N]: ReturnType<L>}}
 */
export default function ModuleWrapper(object, name, lambda) {
  Object.defineProperty(object, name, {
    get() {
      // Redefine this accessor property as a data property.
      // Delete it first, to rule out "too much recursion" in case object is
      // a proxy whose defineProperty handler might unwittingly trigger this
      // getter again.
      Reflect.deleteProperty(object, name);
      const value = lambda.apply(object);
      Object.defineProperty(object, name, {
        value,
        writable: true,
        configurable: true,
        enumerable: true,
      });
      return value;
    },
    configurable: true,
    enumerable: true,
  });
  // @ts-expect-error - object as O & {[name in N]: L}
  return object;
}
